package com.zhao.controller;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhao.po.Car;
import com.zhao.po.Msg;
import com.zhao.po.Product;
import com.zhao.po.Shipment;
import com.zhao.po.User;
import com.zhao.po.vo.OrderDetail;
import com.zhao.po.vo.OrderItemDetail;
import com.zhao.po.vo.OrderUserDetail;
import com.zhao.service.CarService;
import com.zhao.service.OrderService;
import com.zhao.service.ShipmentService;
import com.zhao.service.UserService;
import com.zhao.utils.CommonUtils;
import com.zhao.utils.LogUtil;

@Controller
@RequestMapping("/order")
public class OrderController {

	@Autowired
	private OrderService orderService;

	@Autowired
	private CarService carService;

	@Autowired
	private ShipmentService shipmentService;

	@Autowired
	private UserService userService;

	// ==================先写简单的CRUD=================

	/**
	 * 返回json数据可以提高扩展性。(不是浏览器也可以解析，其他平台类似Android) 这里要设想到： 这里的查询是涉及到分页的
	 * 
	 * 传入的orderDetail对象是传入的条件过滤对象
	 * 
	 * @return
	 */
	@RequestMapping("/getOrders")
	@ResponseBody
	public Msg getOrders(@RequestParam(value = "pn", defaultValue = "1") Integer pn, OrderUserDetail orderDetail)
			throws Exception {
		// 这本不是一个分页查询，但是为了实现分页查询，在这里我们 引入了PageHelper插件
		PageHelper.startPage(pn, CommonUtils.PAGESIZE);
		List<OrderUserDetail> Orders = orderService.getAll(orderDetail);
		// 将我们查询的数据分装成pageInfo对象
		PageInfo<OrderUserDetail> page = new PageInfo<OrderUserDetail>(Orders, CommonUtils.PAGESIZE);
		return Msg.success().add("page", page);

	}

	/**
	 * 根据id查询订单，下面是用来查看订单的订单详情(查看订单下面具体的商品列表)
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/getOrderDetail/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Msg getOrderDetail(@PathVariable("id") String id) {
		try {
			Integer orderid = Integer.parseInt(id);
			OrderDetail order = orderService.getOrderDetail(orderid);
			return Msg.success().add("order", order);

		} catch (Exception e) {
			LogUtil.addErrorLog("订单详细查看", "OrderController.addUser", id, null, e);
			return Msg.fail().add("erroMsg", e.getMessage());
		}

	}

	// /**
	// * 这里用于订单拣货
	// * @param id
	// * @return
	// * @throws Exception
	// */
	// @RequestMapping(value = "/pickOrder/{id}", method = RequestMethod.GET)
	// @ResponseBody
	// public Msg pickOrder(@PathVariable("id") String id) throws Exception {
	//
	// orderService.pickOrder(Integer.parseInt(id));
	// return Msg.success();
	// }

	/**
	 * 订单添加 这里使用了JSR303校验（我们需不需要添加订单这个功能）
	 * 
	 * 添加订单，执行这个操作的业务前提是用户已经存在了，或者登陆了，我们添加的时候只需要回去操作他的用户的id即可
	 * 所以这里要考虑的是我们需要登录操作。登录之后将用户对象的信息存储到session中
	 * 
	 * 页面提交过来的信息有哪些？ 订单中包含的商品:
	 * 
	 * @return
	 */
	@RequestMapping(value = "/addOrder", method = RequestMethod.POST)
	@ResponseBody
	// 这里加上 @RequestBody 是在测试的时候，我们传递过来的是json字符串
	public Msg addOrder(@Valid OrderItemDetail order, BindingResult result) throws Exception {
		if (result.hasErrors()) {
			// 校验失败
			Map<String, Object> map = new HashMap<>();
			List<FieldError> errors = result.getFieldErrors();
			for (FieldError fieldError : errors) {
				System.out.println("错误的字段名：" + fieldError.getField());
				System.out.println("错误信息：" + fieldError.getDefaultMessage());
				map.put(fieldError.getField(), fieldError.getDefaultMessage());
			}
			return Msg.fail().add("errorFields", map);
		} else {
			// 校验之后没有问题：进行添加订单的业务操作
			// 1.从session中或者其他地方获取到正在操作的用户的id
			// 2.

			// orderService.add(order);
			return Msg.success();
		}

	}

	/**
	 * 更行订单信息 在这里进行需要请求方式是PUT，他在页面的表达方式是post请求+传送过来的数据加上“_method=put”
	 * 不过，Spring提供了HttpPutFormContentFilter，让我们可以在Ajax中直接发送PUT请求
	 * 
	 * 修改订单
	 * 
	 * @param order
	 * @return
	 */
	@RequestMapping(value = "/updateOrder/{orderId}", method = RequestMethod.PUT)
	@ResponseBody
	public Msg updateOrder(@Valid OrderUserDetail order, BindingResult result) throws Exception {
		if (result.hasErrors()) {
			// 校验失败
			Map<String, Object> map = new HashMap<>();
			List<FieldError> errors = result.getFieldErrors();
			for (FieldError fieldError : errors) {
				System.out.println("错误的字段名：" + fieldError.getField());
				System.out.println("错误信息：" + fieldError.getDefaultMessage());
				map.put(fieldError.getField(), fieldError.getDefaultMessage());
			}
			return Msg.fail().add("errorFields", map);
		} else {
			orderService.updateorder(order);
			return Msg.success();
		}
	}

	/**
	 * // 订单无法删除： 如果他删除的话需要先将外键关联删除掉 这个方法是删除 单个批量二合一 批量删除：1-2-3(前端使用—来连接id)
	 * 单个删除：1
	 * 
	 * @param id
	 * @return
	 */
	// @RequestMapping(value = "/deleteorder/{ids}", method =
	// RequestMethod.DELETE)
	// @ResponseBody
	// public Msg deleteorder(@PathVariable("ids") String ids) throws Exception
	// {
	// // 批量删除
	// if (ids.contains("-")) {
	// List<Integer> del_ids = new ArrayList<>();
	// String[] str_ids = ids.split("-");
	// // 组装id的集合
	// for (String id : str_ids) {
	// del_ids.add(Integer.parseInt(id));
	// }
	// orderService.deleteorder(del_ids);
	//
	// } else {
	// Integer id = Integer.parseInt(ids);
	// orderService.deleteorder(id);
	// }
	// return Msg.success();
	// }

	/**
	 * 在订单控制器处实现处理订单====== 分拣配货
	 * 
	 * @param id
	 *            既然需要分拣配货就需要根据我们的订单列表中的id来处理订单
	 * @return
	 */
	@RequestMapping(value = "/dealOrder/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Msg dealOrder(@PathVariable("id") String id) throws Exception {

		orderService.dealOrder(Integer.parseInt(id));
		return Msg.success();
	}

	// 需要实现的需求： 物流订单的分配拣货
	/**
	 * 订单拣货：处理订单 实现思路： 1.要处理这个订单的货物。 根据id获取出这个订单中的详细信息 2. 将这些货物装车： 2.1
	 * 
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/pickOrder/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Msg pickOrder(@PathVariable("id") String id) {
		Integer orderid = Integer.parseInt(id);

		// 1.获取到订单的明细列表
		OrderDetail orderDetail = orderService.getOrderDetail(orderid);
		if (orderDetail != null) {

			// 2.获取可用的车辆
			Car car = carService.findCar();
			if (car != null) {
				/*
				 * 存在可用车辆 ---车辆装货：
				 *
				 * 1： 解析订单详情 2： 生成一条或者多条shipment记录
				 * 
				 */
				// 构建一个装运对象
				Shipment shipment = new Shipment();
				// 设置装运的负责人id
				// shipment.setShipperid(shipperid);

				// 设置订单客户id
				int userId = orderDetail.getCustomerid();
				shipment.setCustomerid(userId);
				// 设置装运起始点id

				// 设置装运的终点id,从订单用户那里获取
				shipment.setEndid(userService.getById(userId).getSendaddrid());

				// 设置预计装运日期

				/**
				 * 装运订单商品 需要判断这辆车是否能够装完订单中的全部商品
				 * 
				 */

				// 计算出订单中的商品的总重量和体积
				List<OrderItemDetail> Items = orderDetail.getItems();
				BigDecimal hascontain = car.getHascontain();
				BigDecimal hasweight = car.getHasweight();
				// 汽车容纳的体积
				BigDecimal maxVolume = car.getCarheight().multiply(car.getCarlength()).multiply(car.getCarwith());

				BigDecimal totalcontain = new BigDecimal(0);
				BigDecimal totalweight = new BigDecimal(0);
				// 遍历订单明细，获取订单商品的总体积和总重量
				for (OrderItemDetail item : Items) {
					// 计算商品的重量和体积
					Product product = item.getProduct();
					BigDecimal productCount = new BigDecimal(item.getProductcount());
					// 商品的体积
					BigDecimal volume = product.getProductlenth().multiply(product.getProductwith())
							.multiply(product.getProductheight());

					// 加到商品总体积和中体重中
					totalcontain.add(volume.multiply(productCount));
					totalweight.add(product.getProductweight().multiply(productCount));
				}

				// 比较订单中商品容量和汽车的容量来判断这辆车是否能够完整的容纳这个订单

				if (car.getMaxweight().subtract(hasweight).compareTo(totalweight) == 1
						&& maxVolume.compareTo(totalcontain) == 1) {
					// 车辆完全能够容纳订单
					// 1:更新汽车的容量
					car.setHascontain(hascontain.add(totalcontain));
					car.setHasweight(hasweight.add(totalweight));
					carService.updateCar(car);
					// 设置装运的车辆
					shipment.setCarid(car.getCarid());
					//新增一条order_ship记录和一条shipment记录
					shipmentService.saveShipment(orderDetail,shipment);

				} else {
					// 车辆不能够完全容纳订单
					
				}

			} else {
				// 没有可用车辆,采用较简单的处理方法告诉前台没有可用车辆
				return Msg.fail().add("erroMsg", "无可用车辆，稍后再试");

			}

		}

		return Msg.success();

	}
}
